<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  
  
  <link rel="shortcut icon" href="../img/favicon.ico">
  <title>Ⅲ. 序列化与反序列化的过程 - .NET JSON 源码分析</title>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700" />

  <link rel="stylesheet" href="../css/theme.css" />
  <link rel="stylesheet" href="../css/theme_extra.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "\u2162. \u5e8f\u5217\u5316\u4e0e\u53cd\u5e8f\u5217\u5316\u7684\u8fc7\u7a0b";
    var mkdocs_page_input_path = "Procedure.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="../js/jquery-2.1.1.min.js" defer></script>
  <script src="../js/modernizr-2.8.3.min.js" defer></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script> 
  
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href=".." class="icon icon-home"> .NET JSON 源码分析</a>
        <div role="search">
  <form id ="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" title="Type search term here" />
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="..">首页</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../Introduction/">Ⅰ. JSON 与 .Net Core JSON</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../Structure/">Ⅱ. .NET Core JSON 的结构</a>
                    </li>
                </ul>
                <ul class="current">
                    <li class="toctree-l1 current"><a class="reference internal current" href="./">Ⅲ. 序列化与反序列化的过程</a>
    <ul class="current">
    <li class="toctree-l2"><a class="reference internal" href="#_1">序列化的过程</a>
    </li>
    </ul>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../Summary/">Ⅳ. 总结</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="..">.NET JSON 源码分析</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="..">Docs</a> &raquo;</li>
    
      
    
    <li>Ⅲ. 序列化与反序列化的过程</li>
    <li class="wy-breadcrumbs-aside">
      
    </li>
  </ul>
  
  <hr/>
</div>
          <div role="main">
            <div class="section">
              
                <h1 id="iii">Ⅲ. 功能流程分析</h1>
<p>前面我们大致搞清了整个 .NET Core JSON 的类图结构，我们现在来观察一下序列化、反序列化的过程。</p>
<p>我们的考察基于下面这个类：</p>
<pre><code class="language-C#">public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}
</code></pre>
<p>.NET Core JSON 提供了很多不同环境下的 JSON 解编码 API，包括 4 种 JSON 格式：</p>
<ul>
<li>UTF-8 编码文本</li>
<li>字符串</li>
<li>读取器、编写器（Reader、Writer）</li>
<li>异步输入输出流</li>
</ul>
<p>和 2 种 C# 对象格式：</p>
<ul>
<li>指定类型的实例</li>
<li>泛型类型参数指定的类型的实例</li>
</ul>
<p>那么总共就有 8 种不同的 API。它们通过函数重载或者函数重命名的方式在 <code>JsonSerializer</code> 类中实现。</p>
<p>为了简单起见，我们只考察字符串形式的 JSON 文本和指定类型的 C# 对象实例，研究它们的序列化和反序列化过程。</p>
<h2 id="_1">序列化的过程</h2>
<p>一开始，用户程序调用 <code>JsonSerializer</code> 类的 <code>string Serialize(Object, Type, JsonSerializerOptions)</code> 方法：</p>
<pre><code class="language-C#">string jsonString = JsonSerializer.Serialize(weatherForecast);
</code></pre>
<p>这个方法在经过一些处理后，又将工作扔给了私有的 <code>string Serialize&lt;TValue&gt;(TValue, Type, JsonSerializerOptions)</code> 方法：</p>
<pre><code class="language-C#">// ...函数声明
{
    // ...错误处理
    return Serialize&lt;object?&gt;(value, inputType, options);
}
</code></pre>
<p>这个私有的 <code>Serialize</code> 方法，先后实例化了 <code>PooledByteBufferWriter</code> 和 <code>Utf8JsonWriter</code> 两个对象，然后调用 <code>WriteCore</code> 方法完成了序列化的过程，再通过 <code>JsonReaderHelper.TranscodeHelper</code> 方法将结果转码为字符串返回：</p>
<pre><code class="language-C#">private static string Serialize&lt;TValue&gt;(in TValue value, Type inputType, JsonSerializerOptions? options)
{
    // ... 设置选项
    using (var output = new PooledByteBufferWriter(options.DefaultBufferSize))
    {
        using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions()))
        {
            WriteCore(writer, value, inputType, options);
        }
        return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span);
    }
}
</code></pre>
<p><code>WriteCore</code> 是 <code>JsonSerializer</code> 类的一个私有函数，它实例化了 <code>WriteStack</code> 和最初的一个 <code>JsonConverter</code>，并且将它们交给自己的一个重载函数。</p>
<p>这个重载的 <code>WriteCore</code> 函数会判断当前的这个 <code>JsonConverter</code> 是否是直接处理当前对象的转换器。如果是，则调用 <code>converter.WriteCore</code> 方法来序列化这个对象；否则，会调用 <code>jsonConverter.WriteCoreAsObject</code> 方法处理这个对象。</p>
<p><code>jsonConverter.WriteCoreAsObject</code> 方法定义在 <code>JsonConverter&lt;T&gt;</code> 类内，它尝试解析出这个对象的真实类型，然后再调用 <code>converter.WriteCore</code> 处理。</p>
<p><code>converter.WriteCore</code> 方法定义在 <code>JsonConverter&lt;T&gt;</code> 类内，它调用 <code>JsonConverter&lt;T&gt;</code> 内的 <code>TryWrite</code> 方法尝试去写。<code>TryWrite</code> 方法检查当前对象的类型、格式，然后又调用某个具体的转换器类的 <code>Write</code> 方法去尝试写。通常来说，这个具体的转换器类会调用 <code>Utf8JsonWriter</code> 提供的相关写函数去具体写这个值。完成这些工作后逐层返回。</p>
<p>这个过程可以用 UML 时序图表现如下：
<img alt="Serialize" src="../images/serialization.svg" /></p>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../Summary/" class="btn btn-neutral float-right" title="Ⅳ. 总结">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="../Structure/" class="btn btn-neutral" title="Ⅱ. .NET Core JSON 的结构"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
      
      
        <span><a href="../Structure/" style="color: #fcfcfc;">&laquo; Previous</a></span>
      
      
        <span style="margin-left: 15px"><a href="../Summary/" style="color: #fcfcfc">Next &raquo;</a></span>
      
    </span>
</div>
    <script>var base_url = '..';</script>
    <script src="../js/theme.js" defer></script>
      <script src="../search/main.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>
